package org.egomsl.mw.record;

import java.nio.ByteBuffer;

public class RecordImpl implements Record {
    private Key key;
    private byte[] value;


    public RecordImpl() {
        key = new Key();
    }

    public RecordImpl(String key, String value) {
        this(key.getBytes(), value.getBytes());
    }

    public RecordImpl(byte[] key, byte[] value) {
        this(key, Tag.INSERT, System.currentTimeMillis(), value);
    }

    public RecordImpl(byte[] key, Tag tag, long timestamp) {
        this(key, tag, timestamp, null);
    }

    public RecordImpl(byte[] key, Tag tag, long timestamp, byte[] value) {
        this.key = new Key(key, tag, timestamp);
        this.value = value;
    }

    @Override
    public Key getKey() {
        return key;
    }

    public byte[] getValue() {
        return value;
    }

    public int getDataLen() {
        int size = 4 + 1 + 8 + 2 + key.getKeyLen() ;
        if(value != null) size += value.length;
        return size;
    }

    @Override
    public void writeData(ByteBuffer data) {
        data.putInt(getDataLen());
        data.put((byte)key.getTag().ordinal());
        data.putLong(key.getTimestamp());
        data.putShort((short)key.getKeyLen());
        data.put(key.getKeyBytes(), key.getKeyOffset(), key.getKeyLen());
        if(value != null) {
            data.put(value);
        }else {
            data.putInt(0);
        }
    }

    @Override
    public void readData(ByteBuffer data) {
        int dataLen = data.getInt();

        int ord = data.get();
        Tag tag = Tag.getTag(ord);
        if(tag == null) {
            throw new RuntimeException("Unknown tag ordinal: " + ord);
        }
        key.setTag(tag);

        long timestamp = data.getLong();
        key.setTimestamp(timestamp);

        short keyLen = data.getShort();
        if(keyLen <=0 || keyLen > data.remaining()) {
            throw new RuntimeException("Invalid key length for Record: " + keyLen);
        }
        key.setKeyBytes(new byte[keyLen], 0, keyLen);
        data.get(key.getKeyBytes());

        int valueLen = dataLen - 4 - 1 - 8 - 2 - keyLen;
        if(valueLen < 0 || valueLen > data.remaining()) {
            throw new RuntimeException("Invalid value length for Record: " + valueLen);
        }
        if(valueLen > 0) {
            value = new byte[valueLen];
            data.get(value);
        }
    }

    @Override
    public void clear() {
    }
}
